import os
from django.db.models import FileField, CharField, SET_NULL, ForeignKey, Model, IntegerField, CASCADE
from django.db.models.signals import pre_delete, post_init
from django.dispatch import receiver

from subjects.models import Subject
from management.models import User
from projects.FileStorage import MyStorage


class Project(Model):
    student = ForeignKey(User, on_delete=SET_NULL, null=True, related_name="students")
    teacher = ForeignKey(User, on_delete=SET_NULL, null=True, related_name="teachers")
    name = CharField(max_length=30)
    description = CharField(max_length=1000, null=True)
    _statuses = ["send request", "on work", "send to verification", "done"]
    status = CharField(max_length=30)
    subjects = CharField(max_length=100, null=True)
    _levels = ['Проект', 'НОУ']
    level = CharField(max_length=10, null=True)
    _types = ['Исследовательский', 'Информационный', 'Прикладной', 'Творческий']
    type = CharField(max_length=10, null=True)
    problem = CharField(max_length=1000, null=True)
    relevance = CharField(max_length=1000, null=True)
    target = CharField(max_length=1000, null=True)
    tasks = CharField(max_length=1000, null=True)
    expected_results = CharField(max_length=1000, null=True)
    defence_video = CharField(max_length=200, null=True)
    _nominations = ['Учатник районного НОУ', 'Призёр районного НОУ', 'Победитель районного НОУ',
                    'Учатник городского НОУ', 'Призёр городского НОУ', 'Победитель городского НОУ',
                    'Учатник областного НОУ', 'Призёр областного НОУ', 'Победитель областного НОУ',
                    'Учатник всероссийского НОУ', 'Призёр всероссийского НОУ', 'Победитель всероссийского НОУ']
    nominations = CharField(max_length=100, null=True)

    # фильтрация предметов при записи их в бд(что бы не удалось поставить не существующий предмет
    def set_subject(self, subjects: str):
        flag = True
        for subject in subjects.split(','):
            if subject not in [subject.name for subject in Subject.objects.all()]:
                flag = False
        if flag:
            self.subjects = subjects
            self.save()

    # фильтрация статусов при установке их в бд
    def set_status(self, n):
        if n in self._statuses:
            self.status = n
            self.save()

    def set_type(self, project_type):
        print(project_type, project_type in self._types, self._types)
        if project_type in self._types:
            self.type = project_type
            self.save()
    
    def set_level(self, project_level):
        if project_level in self._levels:
            self.level = project_level
            self.save()
    
    def set_nominations(self, s_nominations):
        s_n = s_nominations.split(',')
        for nomination in s_n:
            if nomination not in self._nominations:
                return
        self.nominations = s_nominations


# эта константа показывает сколько версий может быть у одного файла
MAX_FILE_VERSION = 3


def get_upload_path(instance, filename):
    return f'{instance.project.id}/{filename}'


class File(Model):
    _tag = CharField(max_length=20, null=True)
    _tags = ['Реферат', 'Презентация', 'Аннотация', 'Другое']
    project: Project = ForeignKey(Project, related_name='files', on_delete=CASCADE)
    file = FileField(upload_to=get_upload_path, blank=True, null=True, storage=MyStorage)
    version = IntegerField(default=1)
    previous_file: 'File' = ForeignKey('File', related_name="previous", null=True, on_delete=SET_NULL)
    comment = CharField(max_length=1024, null=True)
    name = CharField(max_length=100, null=True)

    # оновление файла
    def update_file(self, file=None):
        if self.version == MAX_FILE_VERSION:
            self.delete()
        elif self.version == 1 and file is not None:
            new_obj = File.objects.create(project=self.project, file=file, version=1, previous_file=self)
            new_obj.set_tag(self._tag)
            new_obj.save()
            self.version += 1
            self.save()
        else:  # если файл находится не в начале и не в конце по версиям
            self.version += 1
            self.save()
        if self.previous_file is not None:
            self.previous_file.update_file()

    # отправление файла в корзину
    def move_to_trash(self):
        if self.version == 1:
            self.version = -1
        self.save()

    # восстановление файла из корзины
    def restore(self):
        self.version = 1
        self.save()

    def set_tag(self, tag):
        if tag in self._tags:
            self._tag = tag
            self.save()
    
    def get_prevent_files(self):
        previous_file = self.previous_file
        previous_files = []
        while previous_file is not None:  # Запуск цикла, пока у предыдущего файла есть предыдущий файл
            previous_files.append(previous_file)
            previous_file: File = previous_file.previous_file
        return previous_files


# Удаление всех предыдущих файлов
@receiver(pre_delete, sender=File)
def delete_file(sender, instance: File, *args, **kwargs):
    if instance.previous_file is not None:
        instance.previous_file.delete()

@receiver(post_init, sender=File)
def set_name(sender, instance, **kwargs):
    instance.name = os.path.split(instance.file.name)[1]
